package devcken.springframework.web.context;

import java.net.InetAddress;

import javax.servlet.ServletContext;

import org.jasypt.encryption.pbe.StandardPBEBigDecimalEncryptor;
import org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor;
import org.jasypt.encryption.pbe.StandardPBEByteEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;

/**
 * 확장 가능한 컨텍스트 로더 리스너로 추가 기능을 위해 {@link org.springframework.web.context.ContextLoaderListener ContextLoaderListener} 를 상속한다.
 * @author Devcken
 */
public class ExtendableContextLoaderListener extends ContextLoaderListener
{
	private final static Logger logger = LoggerFactory.getLogger(ExtendableContextLoaderListener.class);
	
	/**
	 * 정수 Encryptor 의 명칭 파라메터를 받기 위한 키로 사용된다.
	 */
	public static String CONTEXT_INTEGER_ENCRYPTOR_NAME_PARAM = "integerEncryptorName";
	
	/**
	 * 십진수 Encryptor 의 명칭 파라메터를 받기 위한 키로 사용된다.
	 */
	public static String CONTEXT_DECIMAL_ENCRYPTOR_NAME_PARAM = "decimalEncryptorName";
	
	/**
	 * 문자열 Encryptor 의 명칭 파라메터를 받기 위한 키로 사용된다.
	 */
	public static String CONTEXT_STRING_ENCRYPTOR_NAME_PARAM = "stringEncryptorName";
	
	/**
	 * 바이너리 Encryptor 의 명칭 파라메터를 받기 위한 키로 사용된다.
	 */
	public static String CONTEXT_BYTE_ENCRYPTOR_NAME_PARAM = "byteEncryptorName";
	
	/**
	 * 주어진 컨텍스트를 이용해 루트 컨테이너를 초기화한다.
	 * @param servletContext 초기화하려는 루트 컨테이너의 컨텍스트가 전달된다.
	 */
	@Override
	public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
	{
		this.initializeDaoEncryptor(servletContext);
		
		return super.initWebApplicationContext(servletContext);
	}
	
	/**
	 * 주어진 컨텍스트를 이용해 DAO Encryptor 를 초기화한다.
	 * @param servletContext 초기화하려는 루트 컨테이너의 컨텍스트가 전달된다.
	 */
	private void initializeDaoEncryptor(ServletContext servletContext)
	{
		try
		{
			String integerEncryptorName = servletContext.getInitParameter(CONTEXT_INTEGER_ENCRYPTOR_NAME_PARAM);
			String decimalEncryptorName = servletContext.getInitParameter(CONTEXT_DECIMAL_ENCRYPTOR_NAME_PARAM);
			String stringEncryptorName = servletContext.getInitParameter(CONTEXT_STRING_ENCRYPTOR_NAME_PARAM);
			String byteEncryptorName = servletContext.getInitParameter(CONTEXT_BYTE_ENCRYPTOR_NAME_PARAM);
			
			String password = InetAddress.getLocalHost().getHostName();
			
			HibernatePBEEncryptorRegistry encryptorRegistry = HibernatePBEEncryptorRegistry.getInstance();
			
			if (integerEncryptorName != null)
			{
				StandardPBEBigIntegerEncryptor encryptor = new StandardPBEBigIntegerEncryptor();
				
				encryptor.setPassword(password);
				
				encryptorRegistry.registerPBEBigIntegerEncryptor(integerEncryptorName, encryptor);
			}
			
			if (decimalEncryptorName != null)
			{
				StandardPBEBigDecimalEncryptor encryptor = new StandardPBEBigDecimalEncryptor();
				
				encryptor.setPassword(password);
				
				encryptorRegistry.registerPBEBigDecimalEncryptor(decimalEncryptorName, encryptor);
			}
			
			if (stringEncryptorName != null)
			{
				StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
				
				encryptor.setPassword(password);
				
				encryptorRegistry.registerPBEStringEncryptor(stringEncryptorName, encryptor);
			}
			
			if (byteEncryptorName != null)
			{
				StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor();
				
				encryptor.setPassword(password);
				
				encryptorRegistry.registerPBEByteEncryptor(byteEncryptorName, encryptor);
			}
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
	}
}